import { addSeconds, isAfter } from 'date-fns';
import { getRandomId } from './helper';

function makeStorage() {
  function get(key) {
    const data = localStorage.getItem(key);
    try {
      return JSON.parse(data);
    } catch (e) {
      return null;
    }
  }

  function set(key, data) {
    localStorage.setItem(key, JSON.stringify(data));
    return key;
  }

  function remove(key) {
    const data = get(key);
    localStorage.removeItem(key);
    return data;
  }

  return Object.freeze({ get, set, remove });
}

function makeCache({ storage }) {
  const OPTIONS = {
    maxAge: 24 * 60 * 60
  };

  function set(key, data, options = OPTIONS) {
    const { maxAge } = options;
    const expired = addSeconds(new Date(), maxAge);
    storage.set(key, { expired, data }, options);
    return key;
  }

  function get(key) {
    const d = storage.get(key);
    if (!d) return d;
    const { expired, data } = d;
    if (isAfter(new Date(), expired)) return null;
    return data;
  }

  function remove(key) {
    return storage.remove(key);
  }

  return Object.freeze({ get, set, remove });
}

function makePreviewStore({ cache }) {
  const ID_LENGTH = 16;

  function getId() {
    return getRandomId(ID_LENGTH);
  }

  function isIdValid(id) {
    return `${id}`.length === ID_LENGTH;
  }

  function get(id) {
    if (!isIdValid(id)) return null;
    return cache.get(id);
  }

  function isExist(id) {
    if (!isIdValid(id)) return false;
    const data = get(id);
    return data && typeof data === 'object';
  }

  function save(data, options) {
    if (!data || typeof data !== 'object') {
      throw new Error('news data must be an object');
    }
    const { previewId } = data;
    if (!previewId) {
      const id = getId();
      cache.set(id, { previewId: id, ...data }, options);
      return id;
    } else {
      cache.set(previewId, data, options);
      return previewId;
    }
  }

  function remove(id) {
    if (!isIdValid(id)) return false;
    cache.remove(id);
    return true;
  }

  return Object.freeze({ get, isExist, save, remove });
}

const previewStore = makePreviewStore({
  cache: makeCache({ storage: makeStorage() })
});

export default previewStore;
